package com.lancoo.cvas.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.cvas.arrangecourse.ArrangeCourseService;
import com.lancoo.cvas.entity.*;
import com.lancoo.cvas.exception.BizException;
import com.lancoo.cvas.mapper.*;
import com.lancoo.cvas.pojo.common.Deleted;
import com.lancoo.cvas.pojo.common.FixType;
import com.lancoo.cvas.pojo.common.IsEnable;
import com.lancoo.cvas.pojo.constant.GlobalConstant;
import com.lancoo.cvas.pojo.dto.CourseProhibitDto;
import com.lancoo.cvas.pojo.dto.ExcelCourseRule;
import com.lancoo.cvas.pojo.dto.GradeCourseDto;
import com.lancoo.cvas.pojo.dto.ProhibitDto;
import com.lancoo.cvas.pojo.vo.*;
import com.lancoo.cvas.service.*;
import com.lancoo.cvas.util.BatchInsert;
import com.lancoo.cvas.util.Result;
import com.lancoo.cvas.util.TimeCodeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service("ruleCourseProhibitService")
public class RuleCourseProhibitServiceImpl extends ServiceImpl<RuleCourseProhibitMapper, RuleCourseProhibit> implements RuleCourseProhibitService {


    @Resource
    private RuleCourseProhibitMajorService ruleCourseProhibitMajorService;
    @Resource
    private RuleTeachingClassProhibitService ruleTeachingClassProhibitService;
    @Resource
    private RuleRoomProhibitService ruleRoomProhibitService;
    @Resource
    private RuleClassProhibitService ruleClassProhibitService;
    @Resource
    private RuleTeacherTimeService ruleTeacherTimeService;
    @Resource
    private PlanTeachingService planTeachingService;
    @Resource
    private TeachingClassMapper teachingClassMapper;
    @Resource
    private TeachingClassWeekMapper teachingClassWeekMapper;
    @Resource
    private RuleCourseService ruleCourseService;
    @Resource
    private CourseWeekService courseWeekService;
    @Resource
    private ClassInfoService classInfoService;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    private PeriodSchemeMapper periodSchemeMapper;
    @Resource
    private RuleWeekDayService ruleWeekDayService;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private RuleCourseMapper ruleCourseMapper;
    @Resource
    private PlanTeachingMapper planTeachingMapper;
    @Resource
    private RuleTeachingClassProhibitMapper ruleTeachingClassProhibitMapper;
    @Resource
    private ArrangeCourseService arrangeCourseService;

    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private TransactionDefinition def;

    /**
     * @param taskId:
     * @Description: 获取课程固排禁排
     * @Author: liufeng
     * @Date: 2023/12/9 18:59
     * @return:
     */
    @Override
    public RuleCourseProhibitVo getRuleProhibit(Integer taskId, Long id) {
        List<RuleCourseProhibit> courseProhibits = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
                .eq(RuleCourseProhibit::getRuleId, id)
                .eq(RuleCourseProhibit::getDeleted, Deleted.NOT.getCode())
                .list();

        List<RuleCourseProhibitMajor> majors = ruleCourseProhibitMajorService.lambdaQuery()
                .eq(RuleCourseProhibitMajor::getTaskId, taskId)
                .eq(RuleCourseProhibitMajor::getDeleted, Deleted.NOT.getCode())
                .eq(RuleCourseProhibitMajor::getRuleId, id).list();
        List<Major> majorList = new ArrayList<>();
        for (RuleCourseProhibitMajor major : majors) {
            long count = majorList.stream().filter(o -> o.getGradeId().equals(major.getGradeId())
                    && o.getMajorId().equals(major.getMajorId())).count();
            if (count == 0) {
                majorList.add(new Major().setMajorId(major.getMajorId())
                        .setMajorName(major.getMajorName())
                        .setGradeId(major.getGradeId())
                        .setGradeName(major.getGradeName()));
            }
        }
        return new RuleCourseProhibitVo().setProhibits(courseProhibits).setOutMajors(Major.toGradeMajorTree(majorList));
    }

//    @Override
//    public RuleCourseProhibitVo getCourseProhibit(Integer taskId, Long courseId) {
//        RuleCourse rule = ruleCourseService.lambdaQuery()
//                .eq(RuleCourse::getTaskId, taskId)
//                .eq(RuleCourse::getCourseId, courseId).one();
//        this.getRuleProhibit(taskId,rule)
//        return null;
//    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean setCourseProhibit(Integer taskId, CourseProhibitDto courseProhibitList) {
        //获取年级专业
        List<RuleCourseProhibitMajor> majors = courseProhibitList.getMajors();
        //获取禁排课时
        Map<Integer, List<RuleCourseProhibit>> flagMap = courseProhibitList.getProhibits().stream()
                .collect(Collectors.groupingBy(RuleCourseProhibit::getFlag));

        List<String> fTimeCodes = new ArrayList<>();
        if (CollUtil.isNotEmpty(flagMap.get(1))) {
            fTimeCodes = flagMap.get(1).stream().map(RuleCourseProhibit::getTimeCode).collect(Collectors.toList());
        }

        List<String> pTimeCodes = new ArrayList<>();
        if (CollUtil.isNotEmpty(flagMap.get(2))) {
            pTimeCodes = flagMap.get(2).stream().map(RuleCourseProhibit::getTimeCode).collect(Collectors.toList());
        }

        //获取教学班
        List<TeachingClass> teachingClassList = teachingClassMapper.getCourseFix(taskId, courseProhibitList.getProhibits().get(0).getCourseId(), majors);
        List<Long> teachingClassIds = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());

        //检测设置禁排时固排冲突
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            if (CollUtil.isNotEmpty(pTimeCodes)) {
                courseProhibitCheck(taskId, courseProhibitList.getProhibits(), teachingClassIds, pTimeCodes);
            }
            if (CollUtil.isNotEmpty(fTimeCodes)) {
                //检测教学班固排课时是否超过周课时
                courseFixCheckWeekNum(taskId, courseProhibitList.getProhibits(), teachingClassIds, fTimeCodes);

                //检测设置固排时禁排冲突
                courseFixCheck(taskId, courseProhibitList.getProhibits(), teachingClassList, fTimeCodes);
            }
        }

        //修改
        List<RuleCourseProhibit> collect = courseProhibitList.getProhibits().stream().filter(o -> o.getRuleId() != null).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            //都没冲突删除之前的固排禁排信息
            //删除禁排
//            List<Integer> ids = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
//                    .eq(RuleCourseProhibit::getFlag, 2)
//                    .eq(RuleCourseProhibit::getCourseId, courseProhibitList.get(0).getCourseId())
//                    .list().stream().map(RuleCourseProhibit::getId).collect(Collectors.toList());
            this.lambdaUpdate().eq(RuleCourseProhibit::getTaskId, taskId)
                    .eq(RuleCourseProhibit::getFlag, 2)
                    .eq(RuleCourseProhibit::getRuleId, courseProhibitList.getProhibits().get(0).getRuleId())
                    .remove();
            ruleCourseProhibitMajorService.lambdaUpdate()
                    .eq(RuleCourseProhibitMajor::getRuleId, courseProhibitList.getProhibits().get(0).getRuleId())
                    .remove();
            //删除固排
            ruleTeachingClassProhibitService.lambdaUpdate().eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .eq(RuleTeachingClassProhibit::getType, FixType.Course.getCode())
                    .eq(RuleTeachingClassProhibit::getCourseId, courseProhibitList.getProhibits().get(0).getCourseId())
                    .remove();
        }


        //按年级分组
        Map<String, List<RuleCourseProhibitMajor>> grades = courseProhibitList.getMajors().stream().collect(Collectors.groupingBy(RuleCourseProhibitMajor::getGradeName));
        //获取所有年级专业
        Map<String, List<ClassInfo>> gradeAndeMajor = classInfoService.lambdaQuery()
                .eq(ClassInfo::getTaskId, taskId)
                .list().stream().collect(Collectors.groupingBy(ClassInfo::getGradeName));

        String week = teachingClassWeekMapper.getCourseRuleWeek(taskId,
                courseProhibitList.getProhibits().get(0).getCourseId(),
                Deleted.NOT.getCode());

        RuleCourse ruleCourse = new RuleCourse().setId(courseProhibitList.getProhibits().get(0).getRuleId())
                .setTaskId(taskId).setCourseId(courseProhibitList.getProhibits().get(0).getCourseId())
                .setCourseName(courseProhibitList.getProhibits().get(0).getCourseName())
                .setCourseWeek(week)
                .setCourseRange("");
        try {
            ruleCourseService.saveOrUpdate(ruleCourse);
        } catch (Exception e) {
            throw new BizException(5, courseProhibitList.getProhibits().get(0).getCourseName() + "设置失败，课程已存在规则");
        }

        //禁排年级
        majors.forEach(o -> o.setRuleId(ruleCourse.getId()));
        ruleCourseProhibitMajorService.saveBatch(majors);

        //设置范围
        StringBuilder sb = new StringBuilder();

        for (String grade : grades.keySet()) {
            List<RuleCourseProhibitMajor> exit = grades.get(grade);
            List<ClassInfo> all = gradeAndeMajor.get(grade);
            if (exit.size() == all.size()) {
                sb.append(grade).append("全部专业、");
            } else {
                for (String majorName : exit.stream().map(RuleCourseProhibitMajor::getMajorName).collect(Collectors.toList())) {
                    sb.append(grade).append(majorName).append("、");
                }
            }
        }
        String range = sb.substring(0, sb.length() - 1);
        courseProhibitList.getProhibits().forEach(o -> o.setRuleId(ruleCourse.getId()));
        //保存禁排信息
        this.saveBatch(courseProhibitList.getProhibits().stream().filter(o -> o.getFlag() == 2).collect(Collectors.toList()));

        //保存固排信息到教学班
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            for (RuleCourseProhibit ruleCourseProhibit : courseProhibitList.getProhibits().stream().filter(o -> o.getFlag() == 1).collect(Collectors.toList())) {
                ruleTeachingClassProhibitService.saveCourseFix(taskId, teachingClassIds, ruleCourseProhibit, FixType.Course.getCode(), ruleCourseProhibit.getCourseId());

            }
        }
        ruleCourse.setCourseRange(sb.substring(0, sb.length() - 1));
        ruleCourseService.saveOrUpdate(ruleCourse);
        return true;
    }

    private void courseFixCheckWeekNum(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<Long> teachingClassIds, List<String> fTimeCodes) {
        //获取教学班除了该课程之外的固排课时
        Map<Long, List<RuleTeachingClassProhibit>> map = ruleTeachingClassProhibitService.lambdaQuery()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                .eq(RuleTeachingClassProhibit::getFlag, 1)
                .and(o -> {
                    o.isNull(RuleTeachingClassProhibit::getCourseId)
                            .or().ne(RuleTeachingClassProhibit::getCourseId, courseProhibitList.get(0).getCourseId());
                }).list()
                .stream().collect(Collectors.groupingBy(RuleTeachingClassProhibit::getTeachingClassId));

        //获取教学班课程设置
        List<TeachingClassWeek> weekSetting = teachingClassWeekMapper.getCourseWeeekNum(taskId, courseProhibitList.get(0).getCourseId(), teachingClassIds, Deleted.NOT.getCode());
        Map<Long, List<TeachingClassWeek>> weekMap = weekSetting.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));
        for (Long id : map.keySet()) {
            TeachingClassWeek teachingClassWeek = weekMap.get(id).get(0);
            Integer weekNum = teachingClassWeek.getWeekNum();
            Integer connectSection = teachingClassWeek.getConnectSection();
            Integer connectNumber = teachingClassWeek.getConnectNumber();
            List<RuleTeachingClassProhibit> ruleTeachingClassProhibits = map.get(id).stream()
                    .filter(o -> o.getHourType().equals(teachingClassWeek.getHourType()))
                    .collect(Collectors.toList());

            List<String> eTimeCode = ruleTeachingClassProhibits.stream().map(RuleTeachingClassProhibit::getTimeCode).collect(Collectors.toList());
            Collection<String> commonElements = CollectionUtils.intersection(eTimeCode, fTimeCodes);
            if (CollUtil.isNotEmpty(commonElements)) {
                throw new BizException(5, "课程固排的课时重复：" + String.join(",", commonElements));
            }
            //判断分组
            int groupSize = map.get(id).stream()
                    .filter(o -> o.getHourType().equals(teachingClassWeek.getHourType()))
                    .collect(Collectors.groupingBy(RuleTeachingClassProhibit::getFixGroup)).size();
            int saveGroupSize = courseProhibitList.stream().filter(o -> o.getFlag() == 1).collect(Collectors.groupingBy(RuleCourseProhibit::getReserve)).size();
            int allGroup = weekNum - connectSection * connectNumber + connectNumber;
            if (allGroup - groupSize - saveGroupSize < 0) {
                int i = weekNum - connectSection * connectNumber;
                throw new BizException(5, "课程固排的连上课时与课程设置不一致：" + connectSection + "x" + connectNumber + " " + +1 + "x" + i);
            }

            long leave = 0;
            if (weekNum < connectSection * connectNumber) {
                leave = ((long) (weekNum / connectSection) * connectNumber) - eTimeCode.size();
            } else {
                leave = weekNum - eTimeCode.size();
            }

            if (leave - fTimeCodes.size() < 0) {
                throw new BizException(5, "课程固排的课时量超过最大可固排课时：" + leave);
            }

        }
        //没有固排记录时
        TeachingClassWeek teachingClassWeek = weekSetting.get(0);
        Integer weekNum = teachingClassWeek.getWeekNum();
        Integer connectSection = teachingClassWeek.getConnectSection();
        Integer connectNumber = teachingClassWeek.getConnectNumber();
        int saveGroupSize = courseProhibitList.stream().filter(o -> o.getFlag() == 1).collect(Collectors.groupingBy(RuleCourseProhibit::getReserve)).size();
        int allGroup = weekNum - connectSection * connectNumber + connectNumber;
        if (allGroup - saveGroupSize < 0) {
            int i = weekNum - connectSection * connectNumber;
            throw new BizException(5, "课程固排的连上课时与课程设施不一致：" + connectSection + "x" + connectNumber + 1 + "x" + i);
        }
    }

    private void courseFixCheck(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<TeachingClass> teachingClass, List<String> timeCodes) {
        courseFixCheckRoom(taskId, courseProhibitList, teachingClass, timeCodes);
        courseFixCheckTeacher(taskId, courseProhibitList, teachingClass, timeCodes);
        courseFixCheckClass(taskId, courseProhibitList, teachingClass, timeCodes);
        courseFixCheckTeachingClass(taskId, courseProhibitList, teachingClass, timeCodes);
    }

    private void courseFixCheckTeachingClass(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<TeachingClass> teachingClass, List<String> timeCodes) {
        List<Long> teachingClassIds = teachingClass.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());

        List<String> teachingClassTimes = ruleTeachingClassProhibitService.lambdaQuery()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                .eq(RuleTeachingClassProhibit::getFlag, 2)
                .list().stream().map(RuleTeachingClassProhibit::getTimeCode).collect(Collectors.toList());

        //是否冲突
        Collection<String> commonElements = CollectionUtils.intersection(teachingClassTimes, timeCodes);
        if (CollUtil.isNotEmpty(commonElements)) {
            throw new BizException(5, "课程:" + courseProhibitList.get(0).getCourseName()
                    + "的固排课时:" + commonElements.stream().map(Object::toString).collect(Collectors.joining(","))
                    + "固排失败，课程教学班设置了禁排");
        }
    }

    private void courseFixCheckClass(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<TeachingClass> teachingClass, List<String> timeCodes) {
        List<String> ids = teachingClass.stream().map(TeachingClass::getClassId).collect(Collectors.toList());
        HashSet<String> classIds = new HashSet<>();
        for (String id : ids) {
            String[] split = id.split(",");
            classIds.addAll(Arrays.asList(split));
        }
        if (CollUtil.isNotEmpty(classIds)) {
            List<String> classTimes = ruleClassProhibitService.lambdaQuery()
                    .eq(RuleClassProhibit::getTaskId, taskId)
                    .eq(RuleClassProhibit::getDeleted, Deleted.NOT.getCode())
                    .in(RuleClassProhibit::getClassId, classIds)
                    .eq(RuleClassProhibit::getFlag, 2)
                    .list().stream().map(RuleClassProhibit::getTimeCode).collect(Collectors.toList());

            //是否冲突
            Collection<String> commonElements = CollectionUtils.intersection(classTimes, timeCodes);
            if (CollUtil.isNotEmpty(commonElements)) {
                throw new BizException(5, "课程:" + courseProhibitList.get(0).getCourseName()
                        + "的固排课时:" + commonElements.stream().map(Object::toString).collect(Collectors.joining(","))
                        + "固排失败，课程行政班设置了禁排");
            }
        }
    }

    private void courseFixCheckRoom(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<TeachingClass> teachingClass, List<String> timeCodes) {
        List<Long> roomIds = teachingClassWeekService.lambdaQuery()
                .in(TeachingClassWeek::getTeachingClassId,
                        teachingClass.stream().map(TeachingClass::getTeachingClassId)
                                .collect(Collectors.toList()))
                .list().stream().map(TeachingClassWeek::getRoomId).collect(Collectors.toList());

        if (CollUtil.isNotEmpty(roomIds)) {
            List<String> roomTimes = ruleRoomProhibitService.lambdaQuery()
                    .eq(RuleRoomProhibit::getTaskId, taskId)
                    .eq(RuleRoomProhibit::getDeleted, Deleted.NOT.getCode())
                    .in(RuleRoomProhibit::getRoomId, roomIds)
                    .list().stream().map(RuleRoomProhibit::getTimeCode).collect(Collectors.toList());

            //是否冲突
            Collection<String> commonElements = CollectionUtils.intersection(roomTimes, timeCodes);
            if (CollUtil.isNotEmpty(commonElements)) {
                throw new BizException(5, "课程:" + courseProhibitList.get(0).getCourseName()
                        + "的固排课时:" + String.join(",", commonElements)
                        + "固排失败，课程教室设置了禁排");
            }
        }
    }

    private void courseFixCheckTeacher(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<TeachingClass> teachingClass, List<String> timeCodes) {
        List<Long> teachingClassIds = teachingClass.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
        List<String> teacherTimes = ruleTeacherTimeService.getProhibitByTeachingClass(teachingClassIds);

        //是否冲突
        Collection<String> commonElements = CollectionUtils.intersection(teacherTimes, timeCodes);
        if (CollUtil.isNotEmpty(commonElements)) {
            throw new BizException(5, "课程:" + courseProhibitList.get(0).getCourseName()
                    + "的固排课时:" + commonElements.stream().map(Object::toString).collect(Collectors.joining(","))
                    + "固排失败，课程教师设置了禁排");
        }
    }


    private void courseProhibitCheck(Integer taskId, List<RuleCourseProhibit> courseProhibitList, List<Long> teachingClassIds, List<String> pTimeCodes) {
        //获取教学班除了当前课程之外的固排
        List<RuleTeachingClassProhibit> teachingClassProhibits = ruleTeachingClassProhibitService.lambdaQuery()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                .eq(RuleTeachingClassProhibit::getFlag, 1)
                .and(o -> {
                    o.isNull(RuleTeachingClassProhibit::getCourseId)
                            .or().ne(RuleTeachingClassProhibit::getCourseId, courseProhibitList.get(0).getCourseId());
                }).list();
        List<String> exists = teachingClassProhibits.stream().map(RuleTeachingClassProhibit::getTimeCode).collect(Collectors.toList());

        //是否冲突
        Collection<String> commonElements = CollectionUtils.intersection(pTimeCodes, exists);

        if (CollUtil.isNotEmpty(commonElements)) {
            throw new BizException(5, "课程:" + courseProhibitList.get(0).getCourseName()
                    + "的禁排课时:" + commonElements.stream().map(Object::toString).collect(Collectors.joining(","))
                    + "禁排失败，教学班在该课时设置了固排");
        }
    }

    private void courseProhibitCheckV2(Integer taskId, Long courseId, List<Long> teachingClassIds, List<String> pTimeCodes) {
        //获取教学班除了当前课程之外的固排
        List<RuleTeachingClassProhibit> teachingClassProhibits = ruleTeachingClassProhibitService.lambdaQuery()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                .eq(RuleTeachingClassProhibit::getFlag, 1)
                .and(o -> {
                    o.isNull(RuleTeachingClassProhibit::getCourseId)
                            .or().ne(RuleTeachingClassProhibit::getCourseId, courseId);
                })
                .in(RuleTeachingClassProhibit::getTimeCode, pTimeCodes).list();
        List<String> groups = teachingClassProhibits.stream().map(RuleTeachingClassProhibit::getFixGroup)
                .distinct().collect(Collectors.toList());

        if (CollUtil.isNotEmpty(groups)) {
            ruleTeachingClassProhibitService.lambdaUpdate()
                    .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                    .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .in(RuleTeachingClassProhibit::getFixGroup, groups)
                    .remove();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean delCourseProhibit(Integer taskId, Integer ruleId, Long courseId, String gradeId, String schoolId, String term) {
        ruleCourseService.removeById(ruleId);
        //获取年级专业
        List<RuleCourseProhibitMajor> majors = baseMapper.getCourseProhibitMajors(taskId, ruleId);
        //获取教学班
        List<TeachingClass> teachingClass = teachingClassMapper.getCourseFixV2(taskId, gradeId, courseId);
        List<Long> teachingClassIds = teachingClass.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());

        //教学班固排
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            ruleTeachingClassProhibitService.lambdaUpdate()
                    .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .eq(RuleTeachingClassProhibit::getType, FixType.Course.getCode())
                    .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                    .eq(RuleTeachingClassProhibit::getCourseId, courseId)
                    .remove();
        }
        //跟新排课状态
//        teachingClassIds.forEach(o -> arrangeCourseService.manualAdjustmentUpdate(schoolId, term, taskId, null, o));
        arrangeCourseService.manualAdjustmentUpdateRule(schoolId, term, taskId, null, teachingClassIds);


        //删除课程规则 和 年级专业
        this.lambdaUpdate().eq(RuleCourseProhibit::getTaskId, taskId)
                .eq(RuleCourseProhibit::getRuleId, ruleId).remove();
        ruleCourseProhibitMajorService.lambdaUpdate().eq(RuleCourseProhibitMajor::getTaskId, taskId)
                .eq(RuleCourseProhibitMajor::getRuleId, ruleId).remove();
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delCoursdelCourseProhibitBatcheProhibit(Integer taskId, List<BatchCourseRule> rules, String schoolId, String term) {
//        for (BatchCourseRule rule : rules) {
//            delCourseProhibit(taskId,rule.getRuleId(),rule.getCourseId());
//        }
        List<Integer> ruleIds = rules.stream().map(BatchCourseRule::getRuleId).collect(Collectors.toList());
        List<Long> courseIds = rules.stream().map(BatchCourseRule::getCourseId).collect(Collectors.toList());

        //获取年级专业
        List<RuleCourseProhibitMajor> majors = baseMapper.getCourseProhibitMajorsBatch(taskId, ruleIds);
        //获取教学班
        List<TeachingClass> teachingClass = teachingClassMapper.getCourseFixBatch(taskId, courseIds, majors);
        List<Long> teachingClassIds = teachingClass.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());

        //教学班固排
        ruleTeachingClassProhibitService.lambdaUpdate()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .eq(RuleTeachingClassProhibit::getFlag, 1)
                .eq(RuleTeachingClassProhibit::getType, FixType.Course.getCode())
                .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                .in(RuleTeachingClassProhibit::getCourseId, courseIds)
                .remove();

        //跟新排课状态
//        teachingClassIds.forEach(o -> arrangeCourseService.manualAdjustmentUpdate(schoolId, term, taskId, null, o));
        arrangeCourseService.manualAdjustmentUpdateRule(schoolId, term, taskId, null, teachingClassIds);

        //删除课程和年级专业
        ruleCourseService.removeBatchByIds(ruleIds);
        this.lambdaUpdate().eq(RuleCourseProhibit::getTaskId, taskId)
                .in(RuleCourseProhibit::getRuleId, ruleIds).remove();
        ruleCourseProhibitMajorService.lambdaUpdate().eq(RuleCourseProhibitMajor::getTaskId, taskId)
                .in(RuleCourseProhibitMajor::getRuleId, ruleIds).remove();

        return true;
    }

    /**
     * @param taskId:
     * @Description: 获取所有课程禁排信息
     * @Author: liufeng
     * @Date: 2023/12/10 16:18
     * @return:
     */
    @Override
    public List<RuleCourse> getAllCourseProhibit(Integer taskId, String keyword) {
        return baseMapper.getAllCourseProhibit(taskId, Deleted.NOT.getCode(), keyword);
    }

    @Override
    public void timeProhibitSuit(Integer taskId, List<String> timeCodes) {
        List<Integer> ruleIds = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
                .eq(RuleCourseProhibit::getDeleted, Deleted.NOT.getCode())
                .list().stream().map(RuleCourseProhibit::getRuleId).distinct()
                .collect(Collectors.toList());
        this.lambdaUpdate()
                .eq(RuleCourseProhibit::getTaskId, taskId)
                .in(RuleCourseProhibit::getTimeCode, timeCodes)
                .remove();
        List<Integer> ruleIdsNew = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
                .eq(RuleCourseProhibit::getDeleted, Deleted.NOT.getCode())
                .list().stream().map(RuleCourseProhibit::getRuleId).distinct()
                .collect(Collectors.toList());
        List<Integer> ids = CollUtil.subtractToList(ruleIds, ruleIdsNew);
        if (CollUtil.isNotEmpty(ids)) {
            ruleCourseService.lambdaUpdate().eq(RuleCourse::getTaskId, taskId)
                    .in(RuleCourse::getId, ids)
                    .remove();
            ruleCourseProhibitMajorService.lambdaUpdate().eq(RuleCourseProhibitMajor::getTaskId, taskId)
                    .in(RuleCourseProhibitMajor::getId, ids)
                    .remove();
        }
    }


    /**
     * @param taskId:
     * @Description: 获取所有可以禁排的课程
     * @Author: liufeng
     * @Date: 2024/1/11 8:41
     * @return:
     */
    @Override
    public List<CourseAndMajor> getAllProhibitCourses(Integer taskId) {
        List<CourseAndMajor> res = new ArrayList<>();

        List<TeachingClass> teachingClassList = teachingClassMapper.selectList(new LambdaQueryWrapper<TeachingClass>()
                .eq(TeachingClass::getTaskId, taskId)
                .eq(TeachingClass::getDeleted, Deleted.NOT.getCode())
                .eq(TeachingClass::getIsEnable, IsEnable.ENABLE.getCode())
                .eq(TeachingClass::getState, 1)
                .eq(TeachingClass::getFlag, 1)
                .and(o -> {
                    o.ne(TeachingClass::getSubId, 0)
                            .or().isNull(TeachingClass::getSubId);
                }));

        if (CollUtil.isNotEmpty(teachingClassList)) {
            List<Long> tcIds = teachingClassList.stream().map(TeachingClass::getTeachingClassId)
                    .distinct().collect(Collectors.toList());
            List<TeachingClassWeek> teachingClassWeeks = teachingClassWeekMapper.selectList(new LambdaQueryWrapper<TeachingClassWeek>()
                    .in(TeachingClassWeek::getTeachingClassId,
                            tcIds)
                    .eq(TeachingClassWeek::getDeleted, Deleted.NOT.getCode())
                    .eq(TeachingClassWeek::getHourType, 1));

            Map<Long, List<TeachingClass>> courseMap = teachingClassList.stream().collect(Collectors.groupingBy(TeachingClass::getCourseId));

            List<RuleTeachingClassProhibit> teachingClassProhibits = ruleTeachingClassProhibitService.lambdaQuery()
                    .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .in(RuleTeachingClassProhibit::getTeachingClassId, tcIds)
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .eq(RuleTeachingClassProhibit::getHourType, 1)
                    .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode()).list();
            Map<Long, List<RuleTeachingClassProhibit>> fixSizeMap = new HashMap<>();
            if (CollUtil.isNotEmpty(teachingClassProhibits)) {
                fixSizeMap = teachingClassProhibits.stream().collect(Collectors.groupingBy(RuleTeachingClassProhibit::getTeachingClassId));
            }

            for (Long courseId : courseMap.keySet()) {
                List<TeachingClass> teachingClasses = courseMap.get(courseId);
                List<Long> ids = teachingClasses.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
                List<TeachingClassWeek> weeks = teachingClassWeeks.stream().filter(o -> ids.contains(o.getTeachingClassId())).collect(Collectors.toList());
                if (ids.size() != weeks.size()) {
                    continue;
                }
                String weekRange = weeks.get(0).getWeek();
                Integer weekNum = weeks.get(0).getWeekNum();
                Integer connectSection = weeks.get(0).getConnectSection();
                Integer connectNumber = weeks.get(0).getConnectNumber();
                boolean flag = true;
                for (TeachingClassWeek week : weeks) {
                    flag = week.getWeek().equals(weekRange)
                            && Objects.equals(week.getWeekNum(), weekNum)
                            && Objects.equals(week.getConnectNumber(), connectNumber)
                            && Objects.equals(week.getConnectSection(), connectSection);
                    if (!flag) {
                        break;
                    }
                }
                if (flag) {
                    //可选的年级专业
                    List<Major> majorList = new ArrayList<>();
                    List<TeachingClass> courseClassList = courseMap.get(courseId);
                    for (TeachingClass teachingClass : courseClassList) {
                        long count = majorList.stream().filter(o -> o.getGradeId().equals(teachingClass.getGradeId())
                                && o.getMajorId().equals(teachingClass.getMajorId())).count();
                        if (count == 0) {
                            majorList.add(new Major().setMajorId(teachingClass.getMajorId())
                                    .setMajorName(teachingClass.getMajorName())
                                    .setGradeId(teachingClass.getGradeId())
                                    .setGradeName(teachingClass.getGradeName()));
                        }
                    }
                    //已选的年级专业
                    List<RuleCourseProhibit> courseProhibits = null;
                    List<Major> selectedMajorList = new ArrayList<>();
                    RuleCourse rule = ruleCourseService.lambdaQuery()
                            .eq(RuleCourse::getTaskId, taskId)
                            .eq(RuleCourse::getCourseId, courseId)
                            .eq(RuleCourse::getDeleted, Deleted.NOT.getCode()).one();
                    //设置固排禁排时间
                    if (rule != null) {
                        courseProhibits = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
                                .eq(RuleCourseProhibit::getRuleId, rule.getId())
                                .eq(RuleCourseProhibit::getDeleted, Deleted.NOT.getCode())
                                .list();

                        List<RuleCourseProhibitMajor> majors = ruleCourseProhibitMajorService.lambdaQuery()
                                .eq(RuleCourseProhibitMajor::getTaskId, taskId)
                                .eq(RuleCourseProhibitMajor::getDeleted, Deleted.NOT.getCode())
                                .eq(RuleCourseProhibitMajor::getRuleId, rule.getId()).list();
                        for (RuleCourseProhibitMajor major : majors) {
                            long count = selectedMajorList.stream().filter(o -> o.getGradeId().equals(major.getGradeId())
                                    && o.getMajorId().equals(major.getMajorId())).count();
                            if (count == 0) {
                                selectedMajorList.add(new Major().setMajorId(major.getMajorId())
                                        .setMajorName(major.getMajorName())
                                        .setGradeId(major.getGradeId())
                                        .setGradeName(major.getGradeName()));
                            }
                        }
                        List<TeachingClass> fixTeachingClass = teachingClassMapper.getCourseFix(taskId, courseId, majors);
                        Long fixTeachingClassId = fixTeachingClass.get(0).getTeachingClassId();
                        List<RuleTeachingClassProhibit> fixList = ruleTeachingClassProhibitService.lambdaQuery()
                                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                                .eq(RuleTeachingClassProhibit::getFlag, 1)
                                .eq(RuleTeachingClassProhibit::getCourseId, courseId)
                                .eq(RuleTeachingClassProhibit::getTeachingClassId, fixTeachingClassId)
                                .eq(RuleTeachingClassProhibit::getType, FixType.Course.getCode())
                                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode()).list();
                        courseProhibits.addAll(teachingClassFixToCourseProhibit(rule.getId(), fixList));

                    }
                    //设置剩余的
                    int leave = Integer.MAX_VALUE;
                    for (Long tcId : ids) {
                        List<RuleTeachingClassProhibit> fixs = fixSizeMap.get(tcId);
                        if (CollUtil.isNotEmpty(fixs)) {
                            fixs = fixs.stream().filter(o -> o.getCourseId() == null
                                    || !Objects.equals(o.getCourseId(), courseId)).collect(Collectors.toList());
                        }
                        int size = weekNum - (CollUtil.isNotEmpty(fixs) ? fixs.size() : 0);
                        leave = Math.min(leave, size);
                    }

                    res.add(new CourseAndMajor().setCourseId(courseId)
                            .setCourseName(teachingClasses.get(0).getCourseName())
                            .setWeekNum(weekNum)
                            .setConnectSection(connectSection)
                            .setConnectNumber(connectNumber)
                            .setLeave(leave)
                            .setMajorTrees(Major.toGradeMajorTree(majorList))
                            .setRuleCourseProhibits(courseProhibits)
                            .setMajors(Major.toGradeMajorTree(selectedMajorList)));
                }
            }

        }

        return res.stream().filter(o -> o.getLeave() != 0).collect(Collectors.toList());
    }

    private List<RuleCourseProhibit> teachingClassFixToCourseProhibit(Integer ruleId, List<RuleTeachingClassProhibit> fixList) {
        List<RuleCourseProhibit> res = new ArrayList<>();
        if (CollUtil.isNotEmpty(fixList)) {
            for (RuleTeachingClassProhibit fix : fixList) {
                res.add(new RuleCourseProhibit()
                        .setTaskId(fix.getTaskId())
                        .setRuleId(ruleId)
                        .setCourseId(fix.getCourseId())
                        .setFlag(fix.getFlag())
                        .setTimeCode(fix.getTimeCode())
                        .setReserve(fix.getFixGroup())
                        .setSchoolId(fix.getSchoolId())
                        .setDeleted(fix.getDeleted()));
            }
        }
        return res;
    }


    /**
     * @param response:
     * @param taskId:
     * @param importProhibit:
     * @param file:
     * @Description: 导入课程规则
     * @Author: liufeng
     * @Date: 2024/1/17 19:18
     * @return:
     */
    @Override
    public Result importCourseProhibit(HttpServletResponse response, Integer taskId,
                                       ImportProhibit importProhibit, MultipartFile file) {
        List<ProhibitDto> reason = new ArrayList<>();
        List<ExcelCourseRule> excelAllCourseRuleList = readSubClassExcel(file);

        List<CourseAndMajor> allProhibitCourseList = getAllProhibitCourses(taskId);
        List<String> allCourseName = allProhibitCourseList.stream().map(CourseAndMajor::getCourseName).collect(Collectors.toList());
        Map<String, List<CourseAndMajor>> allProhibitCourseMap = allProhibitCourseList.stream().collect(Collectors.groupingBy(CourseAndMajor::getCourseName));
        Map<String, List<ExcelCourseRule>> excelCourseMap = excelAllCourseRuleList.stream().collect(Collectors.groupingBy(ExcelCourseRule::getCourseName));

        List<CourseProhibitDto> insert = new ArrayList<>();

        for (String key : excelCourseMap.keySet()) {
            if (!allCourseName.contains(key)) {
                reason.add(new ProhibitDto().setName(key).setReason("课程名称不存在或该课程不可设置课程规则（课程教学班设置不一致)"));
                continue;
            }
            List<ExcelCourseRule> excelCourseRuleList = excelCourseMap.get(key);
            List<Integer> flags = excelCourseRuleList.stream().map(ExcelCourseRule::getFlag).distinct().collect(Collectors.toList());
            List<Integer> collect = Arrays.asList(1, 2);
            if (CollUtil.isEmpty(flags) || flags.size() > 2
                    || !collect.containsAll(flags)) {
                reason.add(new ProhibitDto().setName(key).setReason("课程的固排/禁排只允许为 1或2"));
                continue;
            }
            if (excelCourseRuleList.stream()
                    .collect(Collectors.groupingBy(ExcelCourseRule::getRange)).size() != 1) {
                reason.add(new ProhibitDto().setName(key).setReason("同一门课程的年级专业需保持一致"));
                continue;
            }
            CourseAndMajor prohibitCourse = allProhibitCourseMap.get(key).get(0);
            List<RuleCourseProhibitMajor> majors = new ArrayList<>();
            ProhibitDto addReason = checkRange(taskId, excelCourseRuleList.get(0).getRange(), prohibitCourse.getMajorTrees(), majors);
            if (addReason != null) {
                reason.add(addReason.setName(key));
                continue;
            }
            //获取timeCode正则表达式
            String timeCodePattern = getTimeCodePattern(importProhibit.getTaskId(), importProhibit.getSchoolId(), importProhibit.getTerm());

            List<RuleCourseProhibit> prohibits = new ArrayList<>();
            //一门课程的每一行
            for (ExcelCourseRule excelCourseRule : excelCourseRuleList) {
                String[] split = excelCourseRule.getTimeCodes().split("/");
                if (split.length == 0) {
                    String s = excelCourseRule.getFlag() == 1 ? "固排时间不合法" : "禁排时间不合法";
                    reason.add(new ProhibitDto().setName(key).setReason("课程的" + s));
                    continue;
                }

                boolean flag = true;
                String uuid = UUID.randomUUID().toString();
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        flag = false;
                        prohibits.clear();
                        String s = excelCourseRule.getFlag() == 1 ? "固排时间" + timeCode + "超出课时方案" : "禁排时间" + timeCode + "超出课时方案";
                        reason.add(new ProhibitDto().setName(key).setReason("课程的" + s));
                        break;
                    }
                    CourseAndMajor courseAndMajor = allProhibitCourseMap.get(key).get(0);
                    Long courseId = courseAndMajor.getCourseId();
                    prohibits.add(new RuleCourseProhibit().setTaskId(taskId)
                            .setReserve(uuid)
                            .setTimeCode(timeCode)
                            .setCourseId(courseId)
                            .setCourseName(key)
                            .setFlag(excelCourseRule.getFlag())
                            .setDeleted(Deleted.NOT.getCode())
                            .setSchoolId(importProhibit.getSchoolId())
                    );
                }
                if (!flag || CollUtil.isEmpty(prohibits)) {
                    break;
                }

            }
            CourseProhibitDto courseProhibitDto = new CourseProhibitDto();
            courseProhibitDto.setMajors(majors);
            courseProhibitDto.setProhibits(prohibits);
            insert.add(new CourseProhibitDto().setMajors(majors).setProhibits(prohibits));
        }
        for (CourseProhibitDto courseProhibitDto : insert) {
            try {
                if (importProhibit.getIsCoverage()) {
                    Long courseId = courseProhibitDto.getProhibits().get(0).getCourseId();
                    RuleCourse one = ruleCourseService.lambdaQuery()
                            .eq(RuleCourse::getTaskId, taskId)
                            .eq(RuleCourse::getCourseId, courseId)
                            .eq(RuleCourse::getDeleted, Deleted.NOT.getCode()).one();
                    if (one != null) {
                        Integer ruleId = one.getId();
                        delCourseProhibit(taskId, ruleId, courseId, one.getGradeId(),importProhibit.getSchoolId(),importProhibit.getTerm());
                    }
                }
                if (CollUtil.isNotEmpty(courseProhibitDto.getProhibits())
                        && CollUtil.isNotEmpty(courseProhibitDto.getMajors())) {
                    setCourseProhibit(taskId, courseProhibitDto);
                }
            } catch (Exception e) {
                reason.add(new ProhibitDto().setName(courseProhibitDto.getProhibits().get(0).getCourseName())
                        .setReason(e.getMessage()));
            }
        }

        //导出
        if (CollUtil.isEmpty(reason)) {
            return Result.ofSuccess();
        }
//        MyExcelUtils.exportExcel(reason,
//                "导入结果", "", ProhibitDto.class,
//                "导入结果" + System.currentTimeMillis(), response);
//        return Result.ofFail(400,999,"部分导入成功");

        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/导入返回-" + System.currentTimeMillis() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("名称", "课时", "原因"));
        List<String> row;
        for (ProhibitDto item : reason) {
            row = Arrays.asList(item.getName(), item.getTimeCode(), item.getReason());
            rows.add(row);
        }
        writer.write(rows, false);
//        ExcelFormatUtil.setFont(writer);

        writer.setColumnWidth(-1, 20);
        writer.setDefaultRowHeight(20);
        writer.close();
        String data = GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
        return Result.ofFail(400, 999, "部分导入失败，失败原因写入文档", data);
    }

    /**
     * @param response:
     * @param taskId:
     * @param importProhibit:
     * @param file:
     * @Description: 导入课程规则
     * @Author: liufeng
     * @Date: 2024/1/17 19:18
     * @return:
     */
    @Override
    public Result importCourseProhibitV2(HttpServletResponse response, Integer taskId,
                                         ImportProhibit importProhibit, MultipartFile file) throws Exception {
        List<ProhibitDto> reason = new ArrayList<>();
        //读取Excel
        List<ExcelCourseRule> excelAllCourseRuleList = readSubClassExcel(file);

        //获取年级和课程信息
        List<GradeCourseDto> allGradeAndCourse = planTeachingMapper.getAllGradeAndCourse(taskId, Deleted.NOT.getCode());
        if (CollUtil.isEmpty(allGradeAndCourse)){
            return Result.ofFail("系统异常");
        }
        //获取课程
        List<String> allCourseName = allGradeAndCourse.stream().map(GradeCourseDto::getCourseName).collect(Collectors.toList());
        //根据课程分组
        Map<String, List<GradeCourseDto>> allProhibitCourseMap = allGradeAndCourse.stream().collect(Collectors.groupingBy(GradeCourseDto::getCourseName));
        Map<String, List<ExcelCourseRule>> excelCourseMap = excelAllCourseRuleList.stream().collect(Collectors.groupingBy(ExcelCourseRule::getCourseName));

        List<CourseProhibitDto> insert = new ArrayList<>();

        for (String key : excelCourseMap.keySet()) {
            if (!allCourseName.contains(key)) {
                reason.add(new ProhibitDto().setName(key).setReason("课程名称不存在或该课程不可设置课程规则（课程教学班设置不一致)"));
                continue;
            }
            //一个课程的规则
            List<ExcelCourseRule> excelCourseRuleList = excelCourseMap.get(key);
            List<Integer> flags = excelCourseRuleList.stream().map(ExcelCourseRule::getFlag).distinct().collect(Collectors.toList());
            List<Integer> collect = Arrays.asList(1, 2);
            if (CollUtil.isEmpty(flags) || flags.size() > 2
                    || !collect.containsAll(flags)) {
                reason.add(new ProhibitDto().setName(key).setReason("课程的固排/禁排只允许为 1或2"));
                continue;
            }
            if (excelCourseRuleList.stream()
                    .collect(Collectors.groupingBy(ExcelCourseRule::getRange)).size() != 1) {
                reason.add(new ProhibitDto().setName(key).setReason("同一门课程的年级需保持一致"));
                continue;
            }
            //获取课程可设置的年级专业
            List<GradeCourseDto> gradeCourseDtos = allProhibitCourseMap.get(key);
            List<RuleCourseProhibitMajor> majors = new ArrayList<>();
            //检测年级专业是否合法
            ProhibitDto addReason = checkRangeV2(taskId, excelCourseRuleList.get(0).getRange(), gradeCourseDtos, majors);
            if (addReason != null) {
                reason.add(addReason.setName(key));
                continue;
            }
            //获取timeCode正则表达式
            String timeCodePattern = getTimeCodePattern(importProhibit.getTaskId(), importProhibit.getSchoolId(), importProhibit.getTerm());

            List<RuleCourseProhibit> prohibits = new ArrayList<>();
            //一门课程的每一行
            for (ExcelCourseRule excelCourseRule : excelCourseRuleList) {
                String[] split = excelCourseRule.getTimeCodes().split("/");
                if (split.length == 0) {
                    String s = excelCourseRule.getFlag() == 1 ? "固排时间不合法" : "禁排时间不合法";
                    reason.add(new ProhibitDto().setName(key).setReason("课程的" + s));
                    continue;
                }

                boolean flag = true;

                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        flag = false;
                        prohibits.clear();
                        String s = excelCourseRule.getFlag() == 1 ? "固排时间" + timeCode + "超出课时方案" : "禁排时间" + timeCode + "超出课时方案";
                        reason.add(new ProhibitDto().setName(key).setReason("课程的" + s));
                        break;
                    }
                    GradeCourseDto courseAndMajor = gradeCourseDtos.get(0);
                    Long courseId = courseAndMajor.getCourseId();

                    //构造课程规则
                    prohibits.add(new RuleCourseProhibit().setTaskId(taskId)
                            .setTimeCode(timeCode)
                            .setCourseId(courseId)
                            .setCourseName(key)
                            .setFlag(excelCourseRule.getFlag())
                            .setDeleted(Deleted.NOT.getCode())
                            .setSchoolId(importProhibit.getSchoolId())
                    );
                }
                //课时不合法或没规则 不执行
                if (!flag || CollUtil.isEmpty(prohibits)) {
                    break;
                }

            }

            //构造设置课程规则
            String jsonString = JSON.toJSONString(prohibits);
           for (RuleCourseProhibitMajor major : majors) {
                List<RuleCourseProhibit> clone = JSON.parseArray(jsonString, RuleCourseProhibit.class);
                insert.add(new CourseProhibitDto()
                        .setMajors(Collections.singletonList(major))
                        .setProhibits(clone));
            }
        }
        for (CourseProhibitDto courseProhibitDto : insert) {
            TransactionStatus status = transactionManager.getTransaction(def);
            try {
                Long courseId = courseProhibitDto.getProhibits().get(0).getCourseId();
                String gradeId = courseProhibitDto.getMajors().get(0).getGradeId();
                //覆盖 删除原来的
                if (importProhibit.getIsCoverage()) {
                    RuleCourse one = ruleCourseService.lambdaQuery()
                            .eq(RuleCourse::getTaskId, taskId)
                            .eq(RuleCourse::getCourseId, courseId)
                            .eq(RuleCourse::getGradeId,gradeId)
                            .eq(RuleCourse::getDeleted, Deleted.NOT.getCode()).one();
                    //如果存在  删除
                    if (one != null) {
                        Integer ruleId = one.getId();
                        delCourseProhibit(taskId, ruleId, courseId, one.getGradeId(),importProhibit.getSchoolId(),importProhibit.getTerm());
                    }
                }
                if (CollUtil.isNotEmpty(courseProhibitDto.getProhibits())
                        && CollUtil.isNotEmpty(courseProhibitDto.getMajors())) {
                    //设置课程规则
                    setCourseProhibitV2(taskId,gradeId,
                            courseId, courseProhibitDto, importProhibit.getSchoolId(), importProhibit.getTerm());
                }
                transactionManager.commit(status);
            } catch (Exception e) {
                e.printStackTrace();
                if (e instanceof BizException){
                    reason.add(new ProhibitDto().setName(courseProhibitDto.getProhibits().get(0).getCourseName())
                            .setReason(e.getMessage()));
                }
                transactionManager.rollback(status);
            }
        }

        //导出
        if (CollUtil.isEmpty(reason)) {
            return Result.ofSuccess();
        }
//        MyExcelUtils.exportExcel(reason,
//                "导入结果", "", ProhibitDto.class,
//                "导入结果" + System.currentTimeMillis(), response);
//        return Result.ofFail(400,999,"部分导入成功");

        TaskInfo taskInfo = taskInfoService.getById(taskId);
        String storePath = "/" + taskInfo.getTaskName() + "/导入返回-" + System.currentTimeMillis() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;

        FileUtil.del(targetPath);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);
        List<List<String>> rows = new ArrayList<>();
        rows.add(Arrays.asList("名称", "课时", "原因"));
        List<String> row;
        for (ProhibitDto item : reason) {
            row = Arrays.asList(item.getName(), item.getTimeCode(), item.getReason());
            rows.add(row);
        }
        writer.write(rows, false);
//        ExcelFormatUtil.setFont(writer);

        writer.setColumnWidth(-1, 20);
        writer.setDefaultRowHeight(20);
        writer.close();
        String data = GlobalConstant.ACCESS_PATH + "/static/OutputExcel" + storePath;
        return Result.ofFail(400, 999, "部分导入失败，失败原因写入文档", data);
    }

    public String getTimeCodePattern(Integer taskId, String schoolId, String term) {
        List<RuleWeekDay> weekDays = this.getWeekDays(taskId, schoolId, term);
        OptionalInt maxPeriodSchemesSize = weekDays.stream()
                .mapToInt(day -> day.getPeriodSchemes().size())
                .max();

        //最大周次
        int maxWeek = 7;
        //最大节次
        int maxPeriod = maxPeriodSchemesSize.orElse(0);
        // 生成周次的正则表达式
        String weekRegex = maxWeek < 10 ? "(0[1-" + maxWeek + "])" : "(0[1-9]|1[0-" + (maxWeek - 10) + "])";
        // 生成节次的正则表达式
        String periodRegex = maxPeriod < 10 ? "(0[1-" + maxPeriod + "])" : "(0[1-9]|1[0-" + (maxPeriod - 10) + "])";
        return "^" + weekRegex + periodRegex + "$";
    }

    public List<RuleWeekDay> getWeekDays(Integer taskId, String schoolId, String term) {
        List<RuleWeekDay> weekDays = ruleWeekDayService.lambdaQuery()
                .eq(RuleWeekDay::getSchoolId, schoolId)
                .eq(RuleWeekDay::getTerm, term)
                .eq(RuleWeekDay::getDeleted, Deleted.NOT.getCode()).list();
        //填充节次信息
        List<PeriodScheme> periodSchemes = periodSchemeMapper.selectList(new LambdaQueryWrapper<PeriodScheme>()
                .eq(PeriodScheme::getSchoolId, schoolId)
                .eq(PeriodScheme::getTerm, term)
                .eq(PeriodScheme::getDeleted, Deleted.NOT.getCode()));
        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        weekDays.forEach(day -> {
            day.setPeriodSchemes(periodMap.get(day.getBaseSchemeId()));
        });
        return weekDays;
    }

    private ProhibitDto checkRange(Integer taskId, String range, List<GradeMajorTree> majorTrees, List<RuleCourseProhibitMajor> resMajors) {
        ProhibitDto res = new ProhibitDto().setReason("年级专业不合法或为空");
        if (StrUtil.isEmpty(range)) {
            return res;
        }
        String[] split = range.split("、");
        if (split.length == 0) {
            return res;
        }
        //所有年级专业分组
        Map<String, List<Major>> gradeTreeMap = majorTrees.stream().collect(Collectors.toMap(GradeMajorTree::getGradeName, GradeMajorTree::getMajors));
        //一组年级专业
        for (String gradeMajor : split) {
            String[] split1 = gradeMajor.split("：");
            if (split1.length != 2) {
                return res;
            }
            //一个年级下的专业
            List<Major> majorTreeList = gradeTreeMap.get(split1[0]);
            Map<String, Major> majorMap = majorTreeList.stream().collect(Collectors.toMap(Major::getMajorName, o -> o));
            if (CollUtil.isEmpty(majorTreeList)) {
                return res;
            }

            //专业是否存在
            String[] inMajors = split1[1].split("/");
            for (String inMajor : inMajors) {
                Major major = majorMap.get(inMajor);
                if (major == null) {
                    return res;
                }
            }
            for (String inMajor : inMajors) {
                Major major = majorMap.get(inMajor);
                resMajors.add(new RuleCourseProhibitMajor()
                        .setTaskId(taskId)
                        .setGradeId(major.getGradeId())
                        .setGradeName(major.getGradeName())
                        .setMajorId(major.getMajorId())
                        .setMajorName(major.getMajorName())
                        .setDeleted(Deleted.NOT.getCode()));
            }
        }
        return null;
    }

    private ProhibitDto checkRangeV2(Integer taskId, String range, List<GradeCourseDto> majorTrees, List<RuleCourseProhibitMajor> resMajors) {
        ProhibitDto res = new ProhibitDto().setReason("年级不合法或为空");
        if (StrUtil.isEmpty(range)) {
            return res;
        }
        String[] split = range.split("、");
        if (split.length == 0) {
            return res;
        }

        //一组年级
        for (String gradeName : split) {
            //年级是否存在
            GradeCourseDto gradeCourseDto = majorTrees.stream().filter(o -> o.getGradeName().equals(gradeName)).findFirst().orElse(null);
            if (gradeCourseDto == null) {
                res.setReason(gradeName + res.getReason());
                return res;
            }

            resMajors.add(new RuleCourseProhibitMajor()
                    .setTaskId(taskId)
                    .setGradeId(gradeCourseDto.getGradeId())
                    .setGradeName(gradeCourseDto.getGradeName())
                    .setDeleted(Deleted.NOT.getCode()));

        }
        return null;
    }


    public List<ExcelCourseRule> readSubClassExcel(MultipartFile file) {
        List<ExcelCourseRule> excelTeachingClasses = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "课程名称", "禁排/固排", "时间", "年级");
        try {
            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(2).stream()
                    .map(Object::toString).collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("课程名称", "courseName");
            reader.addHeaderAlias("禁排/固排", "flag");
            reader.addHeaderAlias("时间", "timeCodes");
            reader.addHeaderAlias("年级", "range");

            excelTeachingClasses = reader.read(2, 3, ExcelCourseRule.class);
            reader.close();
        } catch (IOException e) {
            log.error("excel导入教学任务失败:{}", e);
        }
        if (excelTeachingClasses.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }
        return excelTeachingClasses;
    }

    /**
     * @param taskId:
     * @Description: 获取年级课程下拉框
     * @Author: liufeng
     * @Date: 2024/3/11 14:11
     * @return:
     */
    @Override
    public List<GradeCourseVo> getAllProhibitCoursesV2(Integer taskId,boolean withRule) {
        //获取年级和课程
        List<GradeCourseDto> gradeCourseDtoList = planTeachingMapper.getAllGradeAndCourse(taskId, Deleted.NOT.getCode());
        List<GradeCourseVo> res = new ArrayList<>();
        if (CollUtil.isNotEmpty(gradeCourseDtoList)) {
            //根据年级分组
            Map<String, List<GradeCourseDto>> map = gradeCourseDtoList.stream().collect(Collectors.groupingBy(GradeCourseDto::getGradeId));
            for (String gradeId : map.keySet()) {
                if (withRule){
                    for (GradeCourseDto gradeCourseDto : map.get(gradeId)) {
                        //获取课程规则
                        List<RuleCourseProhibit> courseProhibitDetail =
                                this.getCourseProhibitDetail(taskId, gradeId, gradeCourseDto.getCourseId());
                        gradeCourseDto.setRuleCourseProhibits(courseProhibitDetail);
                    }
                }
                //年级课程信息
                res.add(new GradeCourseVo().setGradeId(gradeId)
                        .setGradeName(map.get(gradeId).get(0).getGradeName())
                        .setCourseList(map.get(gradeId)));
            }
        }
        //返回 根据年级分组
        return res.stream().sorted(Comparator.comparing(GradeCourseVo::getGradeName)).collect(Collectors.toList());
    }

    @Override
    public List<RuleCourseProhibit> getCourseProhibitDetail(Integer taskId, String gradeId, Long courseId) {
        return ruleCourseMapper.getCourseProhibitDetail(taskId, gradeId, courseId, Deleted.NOT.getCode());
    }


    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean setCourseProhibitV2(Integer taskId, String gradeId, Long courseId, CourseProhibitDto courseProhibitList, String schoolId, String term) {
        //获取年级专业
        List<RuleCourseProhibitMajor> majors = courseProhibitList.getMajors();
        //获取禁排课时
        Map<Integer, List<RuleCourseProhibit>> flagMap = courseProhibitList.getProhibits().stream()
                .collect(Collectors.groupingBy(RuleCourseProhibit::getFlag));

        //固排课时
        List<String> fTimeCodes = new ArrayList<>();
        if (CollUtil.isNotEmpty(flagMap.get(1))) {
            fTimeCodes = flagMap.get(1).stream().map(RuleCourseProhibit::getTimeCode).collect(Collectors.toList());
        }

        //禁排课时
        List<String> pTimeCodes = new ArrayList<>();
        if (CollUtil.isNotEmpty(flagMap.get(2))) {
            pTimeCodes = flagMap.get(2).stream().map(RuleCourseProhibit::getTimeCode).collect(Collectors.toList());
        }

        //获取教学班
        List<TeachingClass> teachingClassList = teachingClassMapper.getCourseFixV2(taskId, gradeId, courseId);
        List<Long> teachingClassIds = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());


        //已存在规则  修改规则
        List<RuleCourseProhibit> collect = courseProhibitList.getProhibits().stream().filter(o -> o.getRuleId() != null).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            //都没冲突删除之前的固排禁排信息
            //删除禁排
//            List<Integer> ids = this.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
//                    .eq(RuleCourseProhibit::getFlag, 2)
//                    .eq(RuleCourseProhibit::getCourseId, courseProhibitList.get(0).getCourseId())
//                    .list().stream().map(RuleCourseProhibit::getId).collect(Collectors.toList());
            //先删除之前的
            this.lambdaUpdate().eq(RuleCourseProhibit::getTaskId, taskId)
                    .eq(RuleCourseProhibit::getRuleId, collect.get(0).getRuleId())
                    .remove();
            ruleCourseProhibitMajorService.lambdaUpdate()
                    .eq(RuleCourseProhibitMajor::getRuleId, collect.get(0).getRuleId())
                    .remove();
            //删除固排
            ruleTeachingClassProhibitService.lambdaUpdate().eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                    .eq(RuleTeachingClassProhibit::getType, FixType.Course.getCode())
                    .eq(RuleTeachingClassProhibit::getCourseId, courseId)
                    .remove();
        }
        WeekDateVo weekDate = taskInfoService.countWeek(taskId);
        long weekCount = weekDate.getWeekCount();
        String format = String.format("%0" + weekCount +
                "d", 1).replace("0","1");

        //规则信息描述
        String reserve = "";
        if (CollUtil.isNotEmpty(pTimeCodes)){
            String fixStr = "禁排：" + pTimeCodes.stream().map(TimeCodeUtil::convert).collect(Collectors.joining(",")) + "；";
            reserve += fixStr;
        }
        if (CollUtil.isNotEmpty(fTimeCodes)){
            String proStr = "固排：" + fTimeCodes.stream().map(TimeCodeUtil::convert).collect(Collectors.joining(","));
            reserve += proStr;
        }


        //保存规则信息
        RuleCourse ruleCourse = new RuleCourse().setId(courseProhibitList.getProhibits().get(0).getRuleId())
                .setTaskId(taskId).setCourseId(courseProhibitList.getProhibits().get(0).getCourseId())
                .setCourseName(courseProhibitList.getProhibits().get(0).getCourseName())
                .setGradeId(gradeId)
                .setCourseRange(courseProhibitList.getMajors().get(0).getGradeName())
                .setCourseWeek(format.replace("0","1"))
                .setReserve(reserve);
        try {
            ruleCourseService.saveOrUpdate(ruleCourse);
        } catch (Exception e) {
            throw new BizException(5, courseProhibitList.getMajors().get(0).getGradeName()
                    + courseProhibitList.getProhibits().get(0).getCourseName() + "设置失败，课程已存在规则");
        }

        //报错禁排年级
        majors.forEach(o -> o.setRuleId(ruleCourse.getId()));
        ruleCourseProhibitMajorService.saveBatch(majors);

        courseProhibitList.getProhibits().forEach(o -> o.setRuleId(ruleCourse.getId()));
        //保存禁排课时信息
        this.saveBatch(courseProhibitList.getProhibits());


        //保存固排信息到教学班  删除冲突的固排信息

        //检测设置禁排时固排冲突
//        if (CollUtil.isNotEmpty(teachingClassIds)){
//
//            if (CollUtil.isNotEmpty(fTimeCodes)) {
//                //检测教学班固排课时是否超过周课时
//                courseFixCheckWeekNum(taskId, courseProhibitList.getProhibits(), teachingClassIds, fTimeCodes);
//
//                //检测设置固排时禁排冲突
//                courseFixCheck(taskId, courseProhibitList.getProhibits(), teachingClassList, fTimeCodes);
//            }
//        }
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            if (CollUtil.isNotEmpty(pTimeCodes)) {
                //检测禁排是否与存在的固排冲突
                //删除原来的固排
                courseProhibitCheckV2(taskId, courseId, teachingClassIds, pTimeCodes);
            }

            //保存固排到教学班
            List<RuleTeachingClassProhibit> add = new ArrayList<>();
            for (TeachingClass teachingClass : teachingClassList) {
                Long teachingClassId = teachingClass.getTeachingClassId();
                List<RuleCourseProhibit> fixList = courseProhibitList.getProhibits().stream()
                        .filter(o -> o.getFlag() == 1)
                        .collect(Collectors.toList());
                for (RuleCourseProhibit ruleCourseProhibit : fixList) {
                    add.add(new RuleTeachingClassProhibit().setTaskId(taskId)
                            .setTeachingClassId(teachingClassId)
                            .setTimeCode(ruleCourseProhibit.getTimeCode())
                            .setSchoolId(ruleCourseProhibit.getSchoolId())
                            .setFlag(ruleCourseProhibit.getFlag())
                            .setType(FixType.Course.getCode())
                            .setHourType(1)
                            .setDeleted(ruleCourseProhibit.getDeleted())
                            .setCourseId(courseId)
                            .setFixGroup(UUID.randomUUID().toString()));
                }

            }

            //批量插入，大数据批量插入
            Consumer<List<RuleTeachingClassProhibit>> consumer = o -> ruleTeachingClassProhibitMapper.addBatch(o);
            BatchInsert.batchSplitInsert(add, consumer);

            //跟新排课状态
            List<Long> tcIds = add.stream().map(RuleTeachingClassProhibit::getTeachingClassId).distinct().collect(Collectors.toList());
//            tcIds.forEach(o -> arrangeCourseService.manualAdjustmentUpdate(schoolId, term, taskId, null, o));
            arrangeCourseService.manualAdjustmentUpdateRule(schoolId, term, taskId, null, tcIds);




            /*
            每一个教学班检测周课时 和重复 固排信息


            //获取教学班除了该课程之外的固排课时
            Map<Long, List<RuleTeachingClassProhibit>> map = ruleTeachingClassProhibitService.lambdaQuery()
                    .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                    .in(RuleTeachingClassProhibit::getTeachingClassId, teachingClassIds)
                    .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                    .eq(RuleTeachingClassProhibit::getFlag, 1)
                    .and(o -> {
                        o.isNull(RuleTeachingClassProhibit::getCourseId)
                                .or().ne(RuleTeachingClassProhibit::getCourseId, courseId);
                    }).list()
                    .stream().collect(Collectors.groupingBy(RuleTeachingClassProhibit::getTeachingClassId));

            //获取教学班课程设置
            List<TeachingClassWeek> weekSetting = teachingClassWeekMapper.getCourseWeeekNum(taskId, courseId, teachingClassIds, Deleted.NOT.getCode());
            Map<Long, List<TeachingClassWeek>> weekMap = weekSetting.stream().collect(Collectors.groupingBy(TeachingClassWeek::getTeachingClassId));

            for (TeachingClass teachingClass : teachingClassList) {
                Long teachingClassId = teachingClass.getTeachingClassId();
                List<String> fixTimes = courseProhibitList.getProhibits().stream().filter(o -> o.getFlag() == 1)
                        .map(RuleCourseProhibit::getTimeCode).collect(Collectors.toList());

//                排除与教学班禁排冲突的固排
                fixTimes = courseFixCheckV2(taskId, teachingClass, fixTimes);
                if (CollUtil.isEmpty(fixTimes)) {
                    continue;
                }

//                排除重复的固排
                TeachingClassWeek teachingClassWeek = weekMap.get(teachingClassId).get(0);
                Integer weekNum = teachingClassWeek.getWeekNum();
                Integer connectSection = teachingClassWeek.getConnectSection();
                Integer connectNumber = teachingClassWeek.getConnectNumber();
                List<RuleTeachingClassProhibit> ruleTeachingClassProhibits = map.get(teachingClassId) == null?
                new ArrayList<>() : map.get(teachingClassId).stream()
                        .filter(o -> o.getHourType().equals(teachingClassWeek.getHourType()))
                        .collect(Collectors.toList());

                List<String> eTimeCode = ruleTeachingClassProhibits.stream().map(RuleTeachingClassProhibit::getTimeCode).collect(Collectors.toList());
                Collection<String> commonElements = CollectionUtils.intersection(eTimeCode, fixTimes);
                fixTimes = fixTimes.stream().filter(o -> !commonElements.contains(o))
                        .collect(Collectors.toList());
                if (CollUtil.isEmpty(fixTimes)) {
                    continue;
                }
                int leave = weekNum - eTimeCode.size();
                //保存固排信息
                if (leave > 0){
                    fixTimes = fixTimes.subList(0, Math.min(leave, fixTimes.size()));
                    List<String> finalFixTimes = fixTimes;
                    List<RuleCourseProhibit> fixList = courseProhibitList.getProhibits().stream().filter(o -> o.getFlag() == 1 && finalFixTimes.contains(o.getTimeCode()))
                            .collect(Collectors.toList());
                    fixList.forEach(o -> o.setReserve(UUID.randomUUID().toString()));
                    ruleTeachingClassProhibitService.saveCourseFixByTeachingClass(taskId, teachingClassId, fixList,
                            FixType.Course.getCode(), 1, courseId);
                }
            }


             */

        }
        return true;


    }


    private List<String> courseFixCheckV2(Integer taskId, TeachingClass teachingClass, List<String> timeCodes) {
        timeCodes = courseFixCheckRoomV2(taskId, teachingClass, timeCodes);
        timeCodes = courseFixCheckTeacherV2(taskId, teachingClass, timeCodes);
        timeCodes = courseFixCheckClassV2(taskId, teachingClass, timeCodes);
        timeCodes = courseFixCheckTeachingClassV2(taskId, teachingClass, timeCodes);
        return timeCodes;
    }

    private List<String> courseFixCheckTeachingClassV2(Integer taskId, TeachingClass teachingClass, List<String> timeCodes) {
        List<String> teachingClassTimes = ruleTeachingClassProhibitService.lambdaQuery()
                .eq(RuleTeachingClassProhibit::getTaskId, taskId)
                .eq(RuleTeachingClassProhibit::getDeleted, Deleted.NOT.getCode())
                .eq(RuleTeachingClassProhibit::getTeachingClassId, teachingClass.getTeachingClassId())
                .eq(RuleTeachingClassProhibit::getFlag, 2)
                .list().stream().map(RuleTeachingClassProhibit::getTimeCode).collect(Collectors.toList());

        //是否冲突
        if (CollUtil.isNotEmpty(teachingClassTimes)) {
            timeCodes = new ArrayList<>(CollectionUtils.subtract(timeCodes, teachingClassTimes));
        }
        return timeCodes;
    }

    private List<String> courseFixCheckClassV2(Integer taskId, TeachingClass teachingClass, List<String> timeCodes) {

        HashSet<String> classIds = new HashSet<>();
        String classId = teachingClass.getClassId();
        if (StrUtil.isNotEmpty(classId)) {
            String[] split = classId.split(",");
            classIds.addAll(Arrays.asList(split));
        }
        if (CollUtil.isNotEmpty(classIds)) {
            List<String> classTimes = ruleClassProhibitService.lambdaQuery()
                    .eq(RuleClassProhibit::getTaskId, taskId)
                    .eq(RuleClassProhibit::getDeleted, Deleted.NOT.getCode())
                    .in(RuleClassProhibit::getClassId, classIds)
                    .eq(RuleClassProhibit::getFlag, 2)
                    .list().stream().map(RuleClassProhibit::getTimeCode).collect(Collectors.toList());

            //是否冲突
            timeCodes = new ArrayList<>(CollectionUtils.subtract(timeCodes, classTimes));
        }
        return timeCodes;
    }

    private List<String> courseFixCheckRoomV2(Integer taskId, TeachingClass teachingClass, List<String> timeCodes) {
        List<Long> roomIds = teachingClassWeekService.lambdaQuery()
                .eq(TeachingClassWeek::getTeachingClassId, teachingClass.getTeachingClassId())
                .eq(TeachingClassWeek::getHourType, 1)
                .list().stream().map(TeachingClassWeek::getRoomId).collect(Collectors.toList());

        if (CollUtil.isNotEmpty(roomIds)) {
            List<String> roomTimes = ruleRoomProhibitService.lambdaQuery()
                    .eq(RuleRoomProhibit::getTaskId, taskId)
                    .eq(RuleRoomProhibit::getDeleted, Deleted.NOT.getCode())
                    .in(RuleRoomProhibit::getRoomId, roomIds)
                    .list().stream().map(RuleRoomProhibit::getTimeCode).collect(Collectors.toList());

            //是否冲突
            timeCodes = new ArrayList<>(CollectionUtils.subtract(timeCodes, roomTimes));
        }
        return timeCodes;
    }

    private List<String> courseFixCheckTeacherV2(Integer taskId, TeachingClass teachingClass, List<String> timeCodes) {
        List<String> teacherTimes = ruleTeacherTimeService.getTeacherProhibitByTeachingClass(taskId, teachingClass.getTeachingClassId());

        //是否冲突
        if (CollUtil.isNotEmpty(teacherTimes)) {
            timeCodes = new ArrayList<>(CollectionUtils.subtract(timeCodes, teacherTimes));
        }
        return timeCodes;
    }
}